package com.winbomb.kingcard.base;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import android.graphics.Color;

import com.winbomb.kingcard.GameMsg;
import com.winbomb.kingcard.IBattle;
import com.winbomb.kingcard.ICard;
import com.winbomb.kingcard.IGameLogic;
import com.winbomb.kingcard.IPlayer;
import com.winbomb.kingcard.utils.GameUtils;

public class Battle implements IBattle {

	/**
	 * 胜利和失败级别的定义
	 * 
	 * 完胜: 自己一张牌没有损失的胜利
	 * 
	 * 溃败: 自己所有的牌都战败
	 * 
	 * 险胜(惜败): 所剩的牌数一样, 靠点数分出胜负的.
	 * 
	 * 小胜(小败): 所剩牌数相差为1;
	 * 
	 * 胜利(失败): 所剩牌数相差为2;
	 * 
	 * 大胜(大败): 所剩牌数相差大于等于3;
	 */
	public static final int UNKNOWN = -1; // 未分胜负
	public static final int WIN_TINY = 0; // 险胜
	public static final int WIN_SMALL = 1; // 小胜
	public static final int WIN_NORMAL = 2; // 胜利
	public static final int WIN_GREAT = 3; // 大胜
	public static final int WIN_PERFECT = 4; // 完胜
	public static final int LOSE_TINY = 0; // 惜败
	public static final int LOSE_SMALL = 1; // 小败
	public static final int LOSE_NORMAL = 2; // 失败
	public static final int LOSE_GREAT = 3; // 大败
	public static final int LOSE_PERFECT = 4; // 溃败

	private IGameLogic game;

	/** 战斗的发起者 */
	private IPlayer invoker;

	/** 战斗的目标 */
	private IPlayer target;

	/** 侵略者 */
	private IPlayer invader;

	/** 保卫者 */
	private IPlayer guarder;

	/** 先手玩家 */
	private IPlayer firstHand;

	/** 侵略的牌 */
	private ICard[] invadeCards;

	/** 进攻的牌 */
	private ICard[] atkCards;

	/** 保卫的牌 */
	private ICard[] guardCards;

	/** 防守的牌 */
	private ICard[] defCards;

	/** 战败的牌 */
	private List<ICard> defeatedCards;

	/** 当前出击牌的索引号 */
	private int currAtkIdx;

	/** 当前出击的牌 */
	private ICard currAtkCard;

	/** 当前进攻对象的索引号 */
	private int currTargetIdx;

	/** 是否是侵略者的回合 */
	private boolean isInvadeTurn;

	/** 侵略者是否赢得了战斗 */
	private boolean isInvadeWin;

	/** 胜利者 */
	private IPlayer winner;
	private ICard[] winnerCards;
	private int winLevel; // 胜利级别

	/** 失败者 */
	private IPlayer loser;
	private ICard[] loserCards;
	private int loseLevel; // 失败级别

	/** 每一次战斗开始时Invade和Guard的卡片数量,用于判断是不是 完胜 */
	private int initInvadeCardCnt;
	private int initGuardCardCnt;
	private int invadeLoss;
	private int guardLoss;

	/** 是否是杀光,如果是杀光,可以追击 */
	private boolean isKillAll;

	/** 战斗是否已经开始 */
	private boolean isStarted;

	public Battle(IGameLogic game) {
		this.game = game;
		this.defeatedCards = new ArrayList<ICard>();
	}

	public void newBattle(IPlayer invoker, IPlayer target) {
		this.invoker = invoker;
		this.target = target;
		this.invader = invoker;
		this.guarder = target;

		this.invadeCards = invader.getBattleCards().toArray(new ICard[GameLogic.MAX_PLAY_CARD]);
		this.guardCards = null;
		this.isKillAll = false;
		this.isStarted = false;

	}

	public void start() {
		// 记录统计信息
		this.invoker.getStatsInfo().record(StatsInfo.ST_BATTLE);
		this.target.getStatsInfo().record(StatsInfo.ST_BATTLE);

		guarder.playCards();
		this.guardCards = guarder.getBattleCards().toArray(new ICard[GameLogic.MAX_PLAY_CARD]);

		// 清除以前所有可能的标记
		GameUtils.clearAllFlags(invadeCards);
		GameUtils.clearAllFlags(guardCards);
		GameUtils.setFlags(invadeCards, Card.IS_UNOPEN_CARD);
		GameUtils.setFlags(guardCards, Card.IS_UNOPEN_CARD);

		this.initInvadeCardCnt = GameUtils.getLiveCardCount(invadeCards);
		this.initGuardCardCnt = GameUtils.getLiveCardCount(guardCards);
		this.winLevel = UNKNOWN;
		this.loseLevel = UNKNOWN;

		if (invader.isHuman()) {
			GameUtils.coverCards(guardCards);
		} else if (guarder.isHuman()) {
			GameUtils.coverCards(invadeCards);
		}

		// 如果防守者是最后的手牌,将获得技能空城
		if (guarder.getCardCount() == 0) {
			for (ICard card : guardCards) {
				if (card != null) {
					card.addSkill(Card.SKILL_EMPTY_CITY);
				}
			}
		}

		this.atkCards = this.invadeCards;
		this.defCards = this.guardCards;
		this.currAtkIdx = -1;
		this.currTargetIdx = -1;
		this.defeatedCards.clear();

		this.isInvadeTurn = true;
		this.isInvadeWin = false;
		this.isStarted = true;
		this.winner = null;
		this.loser = null;
		this.winnerCards = null;
		this.loserCards = null;
		this.firstHand = null;
		game.setCurrPlayer(invader);
	}

	@Override
	public void prepare() {

		ICard invadeGeneral = null;
		ICard guardGeneral = null;

		// 分别获取侵略方和防守方的主将
		for (ICard card : invadeCards) {
			if (card != null && card.testFlag(Card.IS_GENERAL)) {
				invadeGeneral = card;
			}
		}
		for (ICard card : guardCards) {
			if (card != null && card.testFlag(Card.IS_GENERAL)) {
				guardGeneral = card;
			}
		}

		// 如果防守方主将为null,那么进攻方一定取得先机
		if (invadeGeneral != null && guardGeneral == null) {
			isInvadeTurn = true;

		} else if (guardGeneral != null && invadeGeneral == null) {
			isInvadeTurn = false;

		} else if (invadeGeneral != null && guardGeneral != null) {
			int compare = invadeGeneral.compareTo(guardGeneral);
			if (compare > 0) {
				isInvadeTurn = true;

			} else if (compare < 0) {
				isInvadeTurn = false;

			} else {
				isInvadeTurn = true;
			}

		} else {
			isInvadeTurn = true;
		}

		this.atkCards = (isInvadeTurn) ? invadeCards : guardCards;
		this.defCards = (isInvadeTurn) ? guardCards : invadeCards;
		this.firstHand = (isInvadeTurn) ? invader : guarder;
		game.setCurrPlayer(firstHand);
	}

	@Override
	public boolean judge() {

		// 统计战斗中还活着的部队数,以及活着的点数,以分出战斗胜负
		int invadeLiveCardCnt = 0, invadeLivePoint = 0;
		ICard invadeMaxCard = null;
		for (int i = 0; i < invadeCards.length; i++) {
			if (invadeCards[i] != null && !invadeCards[i].testFlag(Card.IS_DEFEATED)) {
				invadeLiveCardCnt++;
				invadeLivePoint += invadeCards[i].getPoint();
				if (invadeMaxCard == null || invadeCards[i].getPoint() > invadeMaxCard.getPoint()) {
					invadeMaxCard = invadeCards[i];
				}
			}
		}

		int guardLiveCardCnt = 0, guardLivePoint = 0;
		ICard guardMaxCard = null;
		for (int i = 0; i < guardCards.length; i++) {
			if (guardCards[i] != null && !guardCards[i].testFlag(Card.IS_DEFEATED)) {
				guardLiveCardCnt++;
				guardLivePoint += guardCards[i].getPoint();
				if (guardMaxCard == null || guardCards[i].getPoint() > guardMaxCard.getPoint()) {
					guardMaxCard = guardCards[i];
				}
			}
		}

		// 判断是胜利和失败
		if (invadeLiveCardCnt != guardLiveCardCnt) {
			// 首先比较谁剩下的牌多
			isInvadeWin = (invadeLiveCardCnt > guardLiveCardCnt) ? true : false;

		} else if (invadeLivePoint != guardLivePoint) {
			// 如果一样,比较点数加起来谁大
			isInvadeWin = (invadeLivePoint > guardLivePoint) ? true : false;

		} else {
			// 如果尚不能分出胜负,则侵略者胜.
			isInvadeWin = true;
		}

		this.winner = (isInvadeWin) ? invader : guarder;
		this.loser = (isInvadeWin) ? guarder : invader;
		this.winnerCards = (isInvadeWin) ? invadeCards : guardCards;
		this.loserCards = (isInvadeWin) ? guardCards : invadeCards;

		// 判断胜利和失败的级别
		if (invadeLiveCardCnt == guardLiveCardCnt) {
			winLevel = WIN_TINY;
			loseLevel = LOSE_TINY;
		} else if (invadeLiveCardCnt == guardLiveCardCnt + 1 || invadeLiveCardCnt == guardLiveCardCnt - 1) {
			winLevel = WIN_SMALL;
			loseLevel = LOSE_SMALL;
		} else if (invadeLiveCardCnt == guardLiveCardCnt + 2 || invadeLiveCardCnt == guardLiveCardCnt - 2) {
			winLevel = WIN_NORMAL;
			loseLevel = LOSE_NORMAL;
		} else if (invadeLiveCardCnt >= guardLiveCardCnt + 3 || invadeLiveCardCnt <= guardLiveCardCnt - 3) {
			winLevel = WIN_GREAT;
			loseLevel = LOSE_GREAT;
		}

		// 判断是不是完胜
		if ((isInvadeWin && invadeLiveCardCnt == initInvadeCardCnt)
				|| (!isInvadeWin && guardLiveCardCnt == initGuardCardCnt)) {
			winLevel = WIN_PERFECT;
		}

		// 判断是不是溃败
		if (GameUtils.getLiveCardCount(loserCards) == 0) {
			loseLevel = LOSE_PERFECT;
		}

		// 判断loser是否已经势力消亡
		// 如果输家是防守方,并且防守方已经空城了,那么防守方灭亡.
		// 如果输家是攻方,并且攻方全军覆没,并且攻方手中也没有牌了,则攻方灭亡
		if ((loser == guarder && loser.getCardCount() == 0)
				|| (loser == invader && invader.getCardCount() == 0 && GameUtils.getLiveCardCount(invadeCards) == 0)) {
			loser.defeated();
		}

		// isKillAll = (isInvadeWin && guardLiveCardCnt == 0);
		isKillAll = (invadeLiveCardCnt == 0 || guardLiveCardCnt == 0);
		// isKillAll = true;

		// 记录统计信息
		winner.getStatsInfo().record(StatsInfo.ST_VICTORY);
		loser.getStatsInfo().record(StatsInfo.ST_DEFEATED);

		return isInvadeWin;
	}

	@Override
	public void finish() {

		// 统计侵略方和防守方分别损失了几张卡片. invaderCards和guardCards中
		// 的标志位DEFEATED的牌要设置为null,不然会被回收回去.
		List<ICard> invBatCards = invader.getBattleCards();
		List<ICard> gudBatCards = guarder.getBattleCards();

		// 去掉所有的Flag,以免对后面产生影响
		GameUtils.clearAllFlags(invadeCards);
		GameUtils.clearAllFlags(guardCards);

		// 将战斗中被击败的牌放回牌堆(选作俘虏的除外)
		game.getCardPile().takeBack(defeatedCards);
		defeatedCards.clear();

		invadeLoss = invBatCards.size() - initInvadeCardCnt;
		guardLoss = gudBatCards.size() - initGuardCardCnt;

		if (!loser.isAlive()) {
			// winner将取回loser所有剩下的牌
			int count = 0;
			List<ICard> loserCards = loser.getBattleCards();
			Iterator<ICard> it = loserCards.iterator();
			while (it.hasNext()) {
				ICard card = it.next();
				if (card != null) {
					winner.takeback(card);
					count++;
					it.remove();
				}
			}

			invadeLoss += (isInvadeWin) ? count : 0 - count;
			guardLoss += (isInvadeWin) ? 0 - count : count;
		}

		this.invader.setAttackTarget(null);
		this.guarder.setAttackSource(null);
		this.firstHand = null;

		// 记录战斗结果
		int winLoss = (isInvadeWin) ? invadeLoss : guardLoss;
		int loseLoss = (isInvadeWin) ? guardLoss : invadeLoss;
		GameMsg msg = new GameMsg(0);
		msg.addPlayer(winner.getPlayerName());
		msg.add("[" + winLoss + "]", Color.RED);
		msg.add(" 战胜 ", Color.RED);
		msg.addPlayer(loser.getPlayerName());
		msg.add("[" + loseLoss + "].", Color.RED);
		game.getGameRecorder().add(msg);

		if (!loser.isAlive()) {
			msg = new GameMsg(0);
			msg.addPlayer(loser.getPlayerName());
			msg.add(" 势力消亡.", Color.RED);
			game.getGameRecorder().add(msg);
		}
	}

	@Override
	public ICard[] getInvadeCards() {
		return this.invadeCards;
	}

	@Override
	public ICard[] getAtkCards() {
		return atkCards;
	}

	@Override
	public ICard[] getGuardCards() {
		return this.guardCards;
	}

	@Override
	public ICard[] getDefCards() {
		return defCards;
	}

	@Override
	public IPlayer getInvader() {
		return this.invader;
	}

	@Override
	public IPlayer getAttacker() {
		return (isInvadeTurn) ? invader : guarder;
	}

	@Override
	public IPlayer getGuarder() {
		return this.guarder;
	}

	@Override
	public IPlayer getDefender() {
		return (isInvadeTurn) ? guarder : invader;
	}

	@Override
	public IPlayer getLoser() {
		return this.loser;
	}

	@Override
	public IPlayer getWinner() {
		return this.winner;
	}

	@Override
	public boolean isInvaderWin() {
		return this.isInvadeWin;
	}

	@Override
	public ICard getCurrAtkCard() {
		return currAtkCard;
	}

	@Override
	public ICard getCurrAtkTarget() {
		return (currTargetIdx != -1) ? defCards[currTargetIdx] : null;
	}

	@Override
	public void setCurrAtkCard(int atkIdx) {

		// 清除之前攻击卡片的标记
		if (currAtkCard != null) {
			currAtkCard.clearFlag(Card.IS_ATK_CARD);
		}

		// 设置新的标记
		currAtkIdx = atkIdx;
		currAtkCard = atkCards[currAtkIdx];
		currAtkCard.setCovered(false);
		currAtkCard.setFlag(Card.IS_ATK_CARD);
		currAtkCard.clearFlag(Card.IS_UNOPEN_CARD);

		// 清除之前可被进攻的标志
		ICard[] tgCards = getDefCards();
		for (ICard tgCard : tgCards) {
			if (tgCard != null) {
				tgCard.clearFlag(Card.UNDER_ATTACK);
			}
		}

		ICard[] atkableCards = getAtkableTargets();
		for (ICard tgCard : atkableCards) {
			if (tgCard != null) {
				tgCard.setFlag(Card.UNDER_ATTACK);
			}
		}

		// 刷新技能标志
		GameUtils.refreshSkillFlags(atkCards);
		GameUtils.refreshSkillFlags(defCards);
	}

	@Override
	public ICard[] getAtkableTargets() {

		ICard[] tgCards = getDefCards();
		ArrayList<ICard> atkTargets = new ArrayList<ICard>();
		for (int i = 0; i < tgCards.length; i++) {

			// 如果是null或者是已经战败的牌,则不可攻击
			if (tgCards[i] == null || tgCards[i].testFlag(Card.IS_DEFEATED)) {
				continue;
			}

			// 如果是暗牌,则可攻击
			if (tgCards[i].testFlag(Card.IS_UNOPEN_CARD)) {

				// 如果在攻击范围之内,则推荐攻击
				if (GameUtils.isInAtkRange(atkCards, currAtkIdx, i)) {
					tgCards[i].setFlag(Card.IS_RECOMMENDED);
				}
				atkTargets.add(tgCards[i]);
				continue;
			}

			// 如果是明牌,看是否能够攻击成功
			if (GameUtils.isAttackSuccess(atkCards, currAtkIdx, tgCards, i)) {
				tgCards[i].setFlag(Card.IS_FIRST_CHOICE);
				atkTargets.add(tgCards[i]);
			}
		}

		return atkTargets.toArray(new ICard[atkTargets.size()]);
	}

	@Override
	public void setCurrAtkTarget(int targetIdx) {

		ICard currAtkTarget = getCurrAtkTarget();

		if (currAtkTarget != null) {
			currAtkTarget.clearFlag(Card.IS_ATK_TARGET);
		}

		currTargetIdx = targetIdx;
		currAtkTarget = defCards[targetIdx];
		currAtkTarget.setFlag(Card.IS_ATK_TARGET);

		// 清除其他牌受攻击的标志
		GameUtils.clearFlags(getDefCards(), Card.UNDER_ATTACK);
	}

	@Override
	public void changeTurn() {

		isInvadeTurn = !isInvadeTurn;

		// 更换进攻牌和防守牌
		atkCards = (isInvadeTurn) ? invadeCards : guardCards;
		defCards = (isInvadeTurn) ? guardCards : invadeCards;

		// 切换游戏的操作者
		game.setCurrPlayer((isInvadeTurn) ? invader : guarder);
	}

	@Override
	public boolean fight() {

		ICard currAtkTarget = getCurrAtkTarget();

		// 清除defcards中的所有推荐/首选标志
		for (ICard card : defCards) {
			if (card != null) {
				card.clearFlag(Card.IS_FIRST_CHOICE);
				card.clearFlag(Card.IS_RECOMMENDED);
			}
		}

		boolean attackerWin = false;
		if (GameUtils.isAttackSuccess(atkCards, currAtkIdx, defCards, currTargetIdx)) {
			if (currAtkCard.getPoint() != 2) {
				currAtkTarget.setFlag(Card.IS_DEFEATED);
				currAtkTarget.clearFlag(Card.IS_ATK_TARGET);
				defeatedCards.add(currAtkTarget);
				setCurrAtkCard(currAtkIdx);
			} else {
				currAtkCard.setFlag(Card.IS_DEFEATED);
				defeatedCards.add(currAtkCard);
				currAtkTarget.setFlag(Card.IS_UNOPEN_CARD);
				atkCards[currAtkIdx] = currAtkTarget;
				currAtkCard = atkCards[currAtkIdx];
				defCards[currTargetIdx] = null;

				List<ICard> atkBattleCards = getAttacker().getBattleCards();
				atkBattleCards.add(currAtkTarget);
				List<ICard> defBattleCards = getDefender().getBattleCards();
				defBattleCards.remove(currAtkTarget);
			}

			attackerWin = true;

			// 记录歼敌数
			if (isInvadeTurn) {
				invader.getStatsInfo().record(StatsInfo.ST_KILL_COUNT);
			} else {
				guarder.getStatsInfo().record(StatsInfo.ST_KILL_COUNT);
			}

		} else {

			// 更换进攻卡片当前回合的操作者
			changeTurn();
			setCurrAtkCard(currTargetIdx);

			attackerWin = false;
		}

		currAtkTarget.setCovered(false);
		// currAtkTarget.clearFlag(Card.IS_ATK_CARD);
		currAtkTarget.clearFlag(Card.IS_ATK_TARGET);
		currAtkTarget.clearFlag(Card.IS_UNOPEN_CARD);

		return attackerWin;
	}

	@Override
	public ICard[] getDefeatedCards() {
		Collections.shuffle(defeatedCards);
		return defeatedCards.toArray(new ICard[defeatedCards.size()]);
	}

	@Override
	public IPlayer getCurrTurner() {
		return (isInvadeTurn) ? invader : guarder;
	}

	@Override
	public void pickCaptives() {
		// 胜者从defeatedCards取回两张牌,败者取回一张牌
		GameUtils.clearAllFlags(defeatedCards);
		Collections.shuffle(defeatedCards);

		List<ICard> winBattleCards = winner.getBattleCards();
		List<ICard> loseBattleCards = loser.getBattleCards();

		boolean isWinnerTurn = true;
		for (int i = 0; i < 3 && defeatedCards.size() > 0; i++) {
			if (isWinnerTurn) {
				winBattleCards.add(defeatedCards.get(0));
				defeatedCards.remove(0);
				isWinnerTurn = false;

			} else {
				if (loser.isAlive()) {
					loseBattleCards.add(defeatedCards.get(0));
					defeatedCards.remove(0);
				}
				isWinnerTurn = true;
			}
		}
	}

	@Override
	public int getCurrAtkCardIdx() {
		return this.currAtkIdx;
	}

	@Override
	public int getCurrAtkTargetIdx() {
		return this.currTargetIdx;
	}

	@Override
	public boolean isKillAll() {
		return isKillAll;
	}

	@Override
	public void chaseAttack() {
		this.invader = winner;
		this.guarder = loser;
		this.invader.setAttackTarget(guarder);
		this.isKillAll = false;

		this.guardCards = null;

		List<ICard> battleCards = winner.getBattleCards();
		this.invadeCards = new ICard[GameLogic.MAX_PLAY_CARD];
		int cardCnt = 0;

		// 把未参加追击的活牌和俘虏牌都收回为手牌
		Iterator<ICard> it = battleCards.iterator();
		while (it.hasNext()) {
			ICard card = it.next();
			if (card != null && card.isSelected() && cardCnt < invadeCards.length) {
				invadeCards[cardCnt++] = card;
			} else {
				winner.takeback(card);
				it.remove();
			}
		}
	}

	@Override
	public ICard[] getLoserCards() {
		return this.loserCards;
	}

	@Override
	public ICard[] getWinnerCards() {
		return this.winnerCards;
	}

	@Override
	public IPlayer getInvoker() {
		return this.invoker;
	}

	@Override
	public IPlayer getTarget() {
		return this.target;
	}

	@Override
	public int getLoseLevel() {
		return this.loseLevel;
	}

	@Override
	public int getWinLevel() {
		return this.winLevel;
	}

	@Override
	public int getInvadeLoss() {
		return invadeLoss;
	}

	@Override
	public int getGuardLoss() {
		return guardLoss;
	}

	@Override
	public boolean isStarted() {
		return this.isStarted;
	}

	@Override
	public IPlayer getFirstHandPlayer() {
		return this.firstHand;
	}
}
